package com.pine.app.module.security.oauth.support.code;


import com.pine.app.module.security.oauth.provider.client.ClientDetails;
import com.pine.app.module.security.oauth.support.AbstractPreparableIntegrationValidator;
import com.pine.app.module.security.core.common.enums.GrantType;
import com.pine.app.module.security.core.common.enums.ErrorType;
import com.pine.app.module.security.oauth.exception.AuthenticationException;
import com.pine.app.module.security.oauth.provider.client.ClientDetailsService;
import com.pine.app.module.security.oauth.support.HttpTokenRequest;
import com.pine.app.module.security.oauth.provider.authrizationCode.AuthenticationCodeService;
import com.pine.app.module.security.oauth.provider.OAuth2Authentication;
import com.pine.app.module.security.oauth.provider.authrizationCode.AuthenticationCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;

/**
 * @author xiaoyuan
 * @create 2019/9/29 14:55
 **/

public class AuthorizationCodeValidator extends AbstractPreparableIntegrationValidator {


    private AuthenticationCodeService codeService;

    @Autowired
    public void setCodeService(AuthenticationCodeService codeService) {
        this.codeService = codeService;
    }
    public AuthorizationCodeValidator() {

    }


    public AuthorizationCodeValidator(ClientDetailsService clientDetailsService, AuthenticationCodeService codeService) {
        super(clientDetailsService);
        this.codeService = codeService;
    }

    @Override
    protected OAuth2Authentication checkParam(HttpTokenRequest request) {
        HttpAuthorizationCodeRequest authorizationCodeRequest = (HttpAuthorizationCodeRequest)request;
        ClientDetails clientDetails =  this.checkClientInfo(request);
        this.checkScope(request.getScope(),clientDetails.getScope());
        if(StringUtils.isBlank(authorizationCodeRequest.getCode())){
            ErrorType.CODE_NOT_NULL.throwThis(AuthenticationException::new);
        }
        this.checkRedirectUri(authorizationCodeRequest.getRedirectUri());
        if(!clientDetails.getRegisteredRedirectUri().contains(authorizationCodeRequest.getRedirectUri())){
            ErrorType.ILLEGAL_REDIRECT_URI.throwThis(AuthenticationException::new,"跳转链接不是注册时的跳转链接");
        }
        AuthenticationCode oauthCode = codeService.getByCode(authorizationCodeRequest.getCode());
        if(oauthCode==null){
            ErrorType.EXPIRED_CODE.throwThis(AuthenticationException::new);
        }
        OAuth2Authentication auth2Authentication =   oauthCode.getOAuth2Authentication();
        if(auth2Authentication==null){
            ErrorType.ILLEGAL_CODE.throwThis(AuthenticationException::new);
        }
        if(!request.getClientCredentials().getPrincipal().equalsIgnoreCase(auth2Authentication.getTokenRequest().getClientId())){
            ErrorType.ILLEGAL_CODE.throwThis(AuthenticationException::new);
        }
        this.codeService.removeByCode(authorizationCodeRequest.getCode());
        return auth2Authentication;
    }

    @Override
    public HttpTokenRequest createRequest(HttpServletRequest request) {
        return new HttpAuthorizationCodeRequest(request);
    }

    @Override
    public String getGrantType() {
        return GrantType.AUTHORIZATION_CODE.getName();
    }
}
